import { useEffect, useMemo, useState } from 'react'
import { useLocation, useNavigate } from 'react-router'
import { useLatest, useMemoizedFn, useRequest, useUpdateEffect } from 'ahooks'
import dayjs from 'dayjs'
import qs from 'qs'
import classNames from 'classnames'
import { Button, Card, Empty, Select, Space, Spin, theme, Tooltip } from 'antd'
import { CopyOutlined, LeftOutlined, RightOutlined, SearchOutlined } from '@ant-design/icons'

import { TextAreaFilter } from '@/components/TextAreaFilter'
import { useControllerRef } from '@/hooks/useAbortController'
import { createPopupSlot } from '@/services/popupSlot'
import { handleCopy } from '@/utils/utils'
import { apiGetListWaybillInfo } from './apis'
import { Header, Wrap } from './components'
import { DetailsDrawer } from './DetailDrawer'
import { TType } from './interface'
import { inpTip, inpValueParse, rmSeparator, SCROLL_BOX_ID, searchValueParse, useCommon } from './utils'
import styles from './styles.module.less'

const INP_DIV_ID = `fba_Track_${Date.now()}`
const popupSlot = createPopupSlot()
const detailsDrawerSlotUpdate = popupSlot.insert(null)

export const List = () => {
  useCommon('list')
  const navigate = useNavigate()
  const { token } = theme.useToken()
  const { pathname, search, hash } = useLocation()

  const searchParsed = useMemo(() => {
    const obj = qs.parse(search, { ignoreQueryPrefix: true })
    return {
      ...searchValueParse(typeof obj.value === 'string' ? obj.value : ''),
      type: (obj.type === 'fbaIds' ? 'fbaIds' : 'waybillNos') as TType,
    }
  }, [search])

  const [type, setType] = useState(searchParsed.type)
  const [value, setValue] = useState<string>(searchParsed.listVal)
  const valueParsed = useMemo(() => inpValueParse(value), [value])

  const changeUrl = useMemoizedFn((t: TType, listJoinEncode: string) => {
    navigate({ pathname, search: `type=${t}&value=${listJoinEncode}` }, { replace: true })
  })

  const controllerRef = useControllerRef()
  const { loading, data, params, run } = useRequest(
    (t, { list }) => {
      controllerRef.current.abort()
      controllerRef.current = new AbortController()
      return apiGetListWaybillInfo({ [t]: list }, controllerRef.current.signal)
    },
    {
      manual: valueParsed.list.length === 0,
      defaultParams: [type, valueParsed] as const,
      onBefore: () => {
        detailsDrawerSlotUpdate(null)
        document.getElementById(SCROLL_BOX_ID)?.scrollTo({ top: 0, behavior: 'smooth' })
      },
      onSuccess: (_data, [t, { listJoinEncode }]) => changeUrl(t, listJoinEncode),
    },
  )

  const latestRef = useLatest({
    searchParsed,
    valueParsed,
    curReqType: params[0] ?? type,
    curReqValueParsed: params[1] ?? valueParsed,
  })

  // 校正url
  const oldSearchHash = `${search}${hash}`
  const newSearchHash = `?type=${searchParsed.type}&value=${searchParsed.listJoinEncode}`
  useEffect(() => {
    if (oldSearchHash !== newSearchHash) {
      const { type, listJoinEncode } = latestRef.current.searchParsed
      changeUrl(type, listJoinEncode)
    }
  }, [changeUrl, latestRef, newSearchHash, oldSearchHash])

  // 从url同步到视图
  useUpdateEffect(() => {
    const { searchParsed, curReqType, curReqValueParsed } = latestRef.current
    if (
      searchParsed.type !== curReqType ||
      `${searchParsed.list.concat().sort()}` !== `${curReqValueParsed.list.concat().sort()}`
    ) {
      run(searchParsed.type, searchParsed)
    }
    setType(searchParsed.type)
    setValue(searchParsed.listVal)
  }, [searchParsed.type, searchParsed.listVal])

  const countInfo = {
    total: data?.length ?? 0,
    found: data?.filter(d => !d.$NotFound).length ?? 0,
    notFound: 0,
  }
  countInfo.notFound = countInfo.total - countInfo.found

  return (
    <Wrap>
      <Header
        right={
          <Space.Compact>
            <Select
              style={{ width: 210 }}
              className={styles.List_select}
              size="large"
              options={[
                { value: 'waybillNos', label: 'FBABEE Shipment ID' },
                { value: 'fbaIds', label: 'FBA Shipment ID' },
              ]}
              value={type}
              onChange={v => setType(v)}
            />
            <TextAreaFilter
              style={{ width: 400 }}
              id={INP_DIV_ID}
              size="large"
              placeholder={inpTip}
              textAreaPlaceholder={inpTip}
              textAreaExtra={inpTip}
              value={value}
              onChange={e => setValue(rmSeparator(e))}
            />
            <Button
              size="large"
              type="primary"
              icon={<SearchOutlined />}
              onClick={() => {
                if (!valueParsed.list.length) {
                  setValue('')
                  document.getElementById(INP_DIV_ID)?.click()
                  return
                }
                run(type, valueParsed)
              }}
            >
              Track
            </Button>
          </Space.Compact>
        }
      />
      <div className={styles.main}>
        <Space style={{ width: '100%', justifyContent: 'space-between' }}>
          <Button size="small" type="link" icon={<LeftOutlined />} onClick={() => navigate(`/track`)}>
            Back to the Track home
          </Button>
          {!!data?.length && (
            <span style={{ color: token.colorTextSecondary }}>
              <b>{countInfo.total}</b> IDs entered, <b>{countInfo.found}</b> found
              {countInfo.notFound && (
                <>
                  , <b style={{ color: token.colorError }}>{countInfo.notFound}</b> not found
                </>
              )}
            </span>
          )}
        </Space>
        <Spin spinning={loading}>
          <Space style={{ width: '100%' }} className={styles.List} direction="vertical" size={12}>
            {!data?.length && <Empty style={{ marginTop: 60 }} description="Please enter the IDs" />}
            {data?.map(item => (
              <Card key={item.$key} bordered={false}>
                <div className={styles.List_item}>
                  <div className={styles.List_item_curr}>{item.logisticsStatusEn || '--'}</div>
                  <Space className={styles.List_item_id} size={4} direction="vertical">
                    <Space size={12}>
                      <Space size={0}>
                        <Tooltip
                          mouseEnterDelay={0.6}
                          title={
                            item.$NotFound && item.waybillNo ? 'FBABEE Shipment ID not found' : 'FBABEE Shipment ID'
                          }
                        >
                          <b style={{ color: item.$NotFound && item.waybillNo ? token.colorError : undefined }}>
                            {item.waybillNo || '--'}
                          </b>
                        </Tooltip>
                        <Button
                          type="text"
                          icon={<CopyOutlined />}
                          disabled={!item.waybillNo}
                          onClick={() => handleCopy(item.waybillNo, { isEn: true })}
                        />
                      </Space>
                      <Space size={0}>
                        <Tooltip
                          mouseEnterDelay={0.6}
                          title={item.$NotFound && item.fbaId ? 'FBA Shipment ID not found' : 'FBA Shipment ID'}
                        >
                          <b style={{ color: item.$NotFound && item.fbaId ? token.colorError : undefined }}>
                            {item.fbaId || '--'}
                          </b>
                        </Tooltip>
                        <Button
                          type="text"
                          icon={<CopyOutlined />}
                          disabled={!item.fbaId}
                          onClick={() => handleCopy(item.fbaId, { isEn: true })}
                        />
                      </Space>
                    </Space>
                    <Space style={{ color: token.colorTextTertiary }} size={12}>
                      <span>{`Shipped On ${item.deliveryDate ? dayjs(item.deliveryDate).$formatSmart($F_YMD) : '--'}`}</span>
                      <span>{`${item.age || '--'} Days`}</span>
                    </Space>
                  </Space>
                  <div className={classNames(styles.List_item_route, item.markFlag === 1 && styles.isDel)}>
                    {item.latestRoute || '--'}
                  </div>
                  <div className={styles.List_item_btn}>
                    <Button
                      style={{ height: 50 }}
                      size="large"
                      type="link"
                      icon={<RightOutlined />}
                      disabled={!!item.$NotFound}
                      onClick={() => {
                        detailsDrawerSlotUpdate(
                          <DetailsDrawer
                            list={data.filter(d => !d.$NotFound)}
                            item={item}
                            destroy={() => detailsDrawerSlotUpdate(null)}
                          />,
                        )
                      }}
                    />
                  </div>
                </div>
              </Card>
            ))}
          </Space>
        </Spin>
      </div>
      <popupSlot.Slot />
    </Wrap>
  )
}
